home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / x68000.arc / SOURCE.ARC / PARSER.MOD < prev    next >
Encoding:
Modula Implementation  |  1986-01-22  |  7.4 KB  |  262 lines

  1. IMPLEMENTATION MODULE Parser;
  2. (* Reads the Source file, and splits each *)
  3. (* line into Label, OpCode & Operand(s).  *)
  4.  
  5.    FROM FileSystem IMPORT
  6.       File, ReadChar;
  7.  
  8.    FROM ErrorX68 IMPORT
  9.       ErrorType, Error;
  10.  
  11.    IMPORT ASCII;
  12.  
  13.  
  14. (*---
  15. (* These objects are declared in the DEFINITION MODULE *)
  16.    CONST
  17.       TokenSize = 8;
  18.       OperandSize = 20;
  19.  
  20.    TYPE
  21.       TOKEN = ARRAY [0..TokenSize] OF CHAR;
  22.       OPERAND = ARRAY [0..OperandSize] OF CHAR;
  23.       STRING = ARRAY [0..80] OF CHAR;
  24.  
  25.    VAR
  26.       OpLoc, SrcLoc, DestLoc : CARDINAL;   (* location of line parts *)
  27.       Line : STRING;
  28.       LineCount : CARDINAL;
  29.                                                                   ---*)
  30.  
  31.  
  32.    PROCEDURE GetLine (VAR f : File; VAR EndFile : BOOLEAN);
  33.    (* Inputs a Line -- up to 80 characters ending in cr/lf -- from a file. *)
  34.  
  35.       CONST
  36.          MAXLINE = 80;
  37.  
  38.       VAR
  39.          i : CARDINAL;
  40.          ch : CHAR;
  41.  
  42.       BEGIN
  43.          i := 0;
  44.          LOOP
  45.             IF f.eof THEN
  46.                EndFile := TRUE;
  47.                EXIT;
  48.             END;
  49.             ReadChar (f, ch);
  50.  
  51.             IF (ch = ASCII.EOL) OR (i >= MAXLINE) THEN
  52.                EXIT;
  53.             END;
  54.  
  55.             Line[i] := ch;
  56.             INC (i);
  57.          END;
  58.  
  59.          Line[i] := 0C;   (* null terminate line *)
  60.          INC (LineCount);
  61.       END GetLine;
  62.  
  63.  
  64.    
  65.    PROCEDURE SplitLine (VAR Label, OpCode : TOKEN; 
  66.                         VAR SrcOp, DestOp : OPERAND);
  67.    (* Separates TOKENs & OPERANDs from Line. *)
  68.  
  69.       CONST
  70.          Quote = 47C;
  71.          StringMAX = 12;
  72.       
  73.       VAR
  74.          i, j : CARDINAL;
  75.          ParCnt : INTEGER;   (* Tracks open parentheses *)
  76.          c : CHAR;
  77.          InQuotes : BOOLEAN;
  78.  
  79.       PROCEDURE Cap (ch : CHAR) : CHAR;
  80.          BEGIN
  81.             IF InQuotes THEN
  82.                RETURN (ch);
  83.             ELSE
  84.                RETURN CAP (ch);
  85.             END;
  86.          END Cap;
  87.  
  88.       PROCEDURE White (ch : CHAR) : BOOLEAN;
  89.          BEGIN
  90.             RETURN ((ch = ASCII.ht) OR (ch = ' '));
  91.          END White;
  92.  
  93.       PROCEDURE Delimiter (ch : CHAR) : BOOLEAN;
  94.          BEGIN
  95.             RETURN (((ch = ' ') AND (NOT InQuotes)) 
  96.                     OR (ch = ASCII.ht) OR (ch = 0C));
  97.          END Delimiter;
  98.  
  99.       PROCEDURE OpDelimiter (ch : CHAR) : BOOLEAN;
  100.          BEGIN
  101.             RETURN ((ch = ',') AND (NOT InQuotes) AND (ParCnt = 0));
  102.          END OpDelimiter;
  103.  
  104.       PROCEDURE Done (ch : CHAR) : BOOLEAN;
  105.       (* look for start of comment or NULL terminator *)
  106.          BEGIN
  107.             RETURN ((ch = ';') OR (ch = 0C) OR ((ch = '*') AND (i = 0)));
  108.          END Done;
  109.  
  110.    
  111.       BEGIN   (* SplitLine *)
  112.          i := 0;
  113.          InQuotes := FALSE;
  114.  
  115.          IF Done (Line[i]) THEN   (* look for blank or all-comment line *)
  116.             RETURN;
  117.          END;
  118.  
  119.          IF White (Line[i]) THEN
  120.             INC (i);
  121.             WHILE White (Line[i]) DO
  122.                INC (i);   (* Skip spaces & tabs *)
  123.             END;
  124.          ELSE   (* Found a Label *)
  125.             j := 0;
  126.             c := Line[i];
  127.             WHILE (NOT Delimiter (c)) AND (j < TokenSize) DO
  128.                Label[j] := CAP (c);
  129.                INC (i);   INC (j);
  130.                c := Line[i];
  131.             END;
  132.             Label[j] := 0C;   (* terminate Label string *)
  133.             IF j = TokenSize THEN
  134.                Error (i, TooLong);
  135.             END;
  136.             WHILE NOT Delimiter (Line[i]) DO 
  137.                INC (i);   (* Skip remainder of Too-Long Token *)
  138.             END;
  139.          END;
  140.  
  141.          WHILE White (Line[i]) DO
  142.             INC (i);
  143.          END;
  144.  
  145.          IF Done (Line[i]) THEN
  146.             RETURN;
  147.          ELSE   (* Found an OpCode *)
  148.             OpLoc := i;
  149.             j := 0;
  150.             c := Line[i];
  151.             WHILE (NOT Delimiter (c)) AND (j < TokenSize) DO
  152.                OpCode[j] := CAP (c);
  153.                INC (i);   INC (j);
  154.                c := Line[i];
  155.             END;
  156.             OpCode[j] := 0C;  
  157.             IF j = TokenSize THEN
  158.                Error (i, TooLong);
  159.             END;
  160.             WHILE NOT Delimiter (Line[i]) DO 
  161.                INC (i);   (* Skip remainder of Too-Long Token *)
  162.             END;
  163.          END;
  164.  
  165.          WHILE White (Line[i]) DO
  166.             INC (i);
  167.          END;
  168.  
  169.          IF Done (Line[i]) THEN
  170.             RETURN;
  171.          ELSE   (* Found 1st Operand *)
  172.             SrcLoc := i;
  173.             j := 0;
  174.             ParCnt := 0;
  175.             c := Line[i];
  176.             IF c = Quote THEN   (* String Constant *)
  177.                SrcOp[j] := c;   
  178.                INC (i);   INC (j);
  179.                REPEAT
  180.                   c := Line[i];
  181.                   SrcOp[j] := c;
  182.                   INC (i);   INC (j);
  183.                UNTIL (c = Quote) OR (j > StringMAX) OR (c = 0C);
  184.                SrcOp[j] := 0C;
  185.                IF j > StringMAX THEN
  186.                   Error (i, TooLong);
  187.                END;
  188.                RETURN;  (* second operand not allowed after string constant *)
  189.             ELSE   (* Normal Operand *)
  190.                WHILE (NOT Delimiter (c)) 
  191.                 AND (NOT OpDelimiter (c)) 
  192.                  AND (j < OperandSize) DO
  193.                   IF c = Quote THEN
  194.                      InQuotes := NOT InQuotes;   (* Toggle Switch *)
  195.                   END;
  196.                   IF NOT InQuotes THEN
  197.                      IF c = '(' THEN
  198.                         INC (ParCnt);
  199.                      END;
  200.                      IF c = ')' THEN
  201.                         DEC (ParCnt);
  202.                      END;
  203.                   END;
  204.                   SrcOp[j] := Cap (c);   (* Switched CAP function *)
  205.                   INC (i);   INC (j);
  206.                   c := Line[i];
  207.                END;
  208.                SrcOp[j] := 0C;
  209.                IF j = OperandSize THEN
  210.                   Error (i, TooLong);
  211.                END;
  212.             END;
  213.             WHILE (NOT Delimiter (Line[i])) AND (NOT OpDelimiter (Line[i])) DO 
  214.                INC (i);   (* Skip remainder of Too-Long Operand *)
  215.             END;
  216.          END;
  217.  
  218.          IF NOT OpDelimiter (Line[i]) THEN
  219.             RETURN;   (* because only one OPERAND *)
  220.          ELSE   (* Found 2nd Operand *)
  221.             INC (i);   (* Skip OpDelimiter (comma) *)
  222.             DestLoc := i;
  223.             j := 0;
  224.             c := Line[i];
  225.             WHILE (NOT Delimiter (c)) AND (j < OperandSize) DO
  226.                DestOp[j] := CAP (c);
  227.                INC (i);   INC (j);
  228.                c := Line[i];
  229.             END;
  230.             DestOp[j] := 0C;
  231.             IF j = OperandSize THEN
  232.                Error (i, TooLong);
  233.             END;
  234.          END;
  235.       END SplitLine;
  236.  
  237.  
  238.  
  239.    PROCEDURE LineParts (VAR f : File; VAR EndFile : BOOLEAN;
  240.                         VAR Label, OpCode : TOKEN; 
  241.                         VAR SrcOp, DestOp : OPERAND);
  242.    (* Reads line, breaks into tokens, on-passes to symbol & code generators *)
  243.  
  244.       BEGIN
  245.          Line := "";
  246.          GetLine (f, EndFile);   (* read a line from the file *)
  247.  
  248.          IF EndFile THEN
  249.             Error (0, EndErr);
  250.          ELSE
  251.             Label := "";   OpCode := "";   SrcOp := "";   DestOp := "";
  252.             SplitLine (Label, OpCode, SrcOp, DestOp);
  253.          END;
  254.       END LineParts;   
  255.  
  256.  
  257.  
  258. BEGIN   (* MODULE Initialization *)
  259.    OpLoc := 0;   SrcLoc := 0;   DestLoc := 0;   LineCount := 0; 
  260. END Parser.
  261.  
  262.